package hhs.scannerapp;


import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.List;
import java.util.Random;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Color;
import android.util.Log;

public class Model {
	private FloatBuffer vertexBuffer, textureBuffer, colorBuffer;
	private ShortBuffer[] indexBuffer;
	float[] texPoints;
	private int numPoints = 0;
	float[] vertices;
	short[][] indexes;
	short[] topInd;
	short[] btmInd;
	int [] textures = new int[1];
	public int edgeSize = 0;
	public int nEdges;
	boolean ready = false;
	int size = 0;

	public void instantiate(List<EdgeModel> edges){
		edgeSize = edges.get(0).edges.size();

		for(EdgeModel edge : edges){
			size+=edge.edges.size();
		}
		numPoints = size;
		nEdges = numPoints/edgeSize;
		indexBuffer = new ShortBuffer[nEdges+2];
		size*=3;
		vertices = new float[3*edgeSize*(nEdges+1)];
		ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length*4);
		byteBuffer.order(ByteOrder.nativeOrder());
		vertexBuffer = byteBuffer.asFloatBuffer();
		int index = 0;
		double[] max = new double[]{0f,0f,0f};
		for(int i = 0; i < edges.size(); i++){

			List<EdgeModel.EdgePoint> em = edges.get(i).edges;

			for(int j = 0; j < em.size(); j++) {

				float[] point = em.get(j).toCartesian();

				for(int k = 0; k < 3; k++) {
					if(Math.abs(point[k]) > max[k])
						max[k] = Math.abs(point[k]);
					vertices[index] = point[k];
					index++;
				}
			}
		}

		for(int i = 3*numPoints; i < vertices.length; i++) {
			vertices[i] = vertices[i-3*numPoints];
		}


		indexes = new short[nEdges+2][];
		for(int i = 0; i < nEdges; i++) {
			indexes[i] = new short[2*edgeSize];
			for(int j = 0; j < edgeSize; j++) {
				indexes[i][2*j] = (short) (i*edgeSize+j);
				indexes[i][2*j+1] = (short)((i+1)*edgeSize + j);
			}
			ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(2*indexes[i].length);
			byteBuffer1.order(ByteOrder.nativeOrder());
			indexBuffer[i] = byteBuffer1.asShortBuffer();
			indexBuffer[i].put(indexes[i]);
			indexBuffer[i].position(0); 
		}

		indexes[nEdges] = new short[nEdges];
		indexes[nEdges+1] = new short[nEdges];
		for(int j = 0; j < nEdges; j++) {
			indexes[nEdges][j] = (short) (j*edgeSize);
			indexes[nEdges+1][j] = (short) ((j+1)*edgeSize-1);
		}
		for(int i = 0; i < 2; i++) {
			ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(2*indexes[i].length);
			byteBuffer1.order(ByteOrder.nativeOrder());
			indexBuffer[i+nEdges] = byteBuffer1.asShortBuffer();
			indexBuffer[i+nEdges].put(indexes[i+nEdges]);
			indexBuffer[i+nEdges].position(0); 			
		}

		vertexBuffer.put(vertices);
		vertexBuffer.position(0);

		texPoints = new float[2*vertices.length];
		for(int i = 0; i < vertices.length; i++) {
			texPoints[2*i] = 1-(i/edgeSize)/((float)nEdges); 
			texPoints[2*i+1] = (i%edgeSize)/((float)edgeSize);
		}

		ByteBuffer byteBuffer111 = ByteBuffer.allocateDirect(4*texPoints.length);
		byteBuffer111.order(ByteOrder.nativeOrder());
		textureBuffer = byteBuffer111.asFloatBuffer();
		textureBuffer.put(texPoints);
		textureBuffer.position(0);

		ready = true;
	}

	public void makeColors(){
		ByteBuffer byteBuffer11 = ByteBuffer.allocateDirect(4*size*4);
		byteBuffer11.order(ByteOrder.nativeOrder());
		colorBuffer = byteBuffer11.asFloatBuffer();
		colorBuffer.clear();
		colorBuffer.position(0);

		float[] colors = new float[4*numPoints];
	
		
		/*float[] triangle = new float[3];
		boolean done = false;
		Log.d("Random Color", "Generating");
		do{
			float a, b, c = 0;
			a = (float)(Math.random() * 500);
			b = (float)(Math.random() * 500);
			if(Math.sqrt(Math.pow(a,2) + Math.pow(b,2)) % 1 == 0 && a != 0 && b != 0) {
				c = (int) (Math.sqrt(Math.pow(a,2) + Math.pow(b,2)));
				triangle = new float[]{a/250000, b/250000, c/250000};
				done = true;
			}
		}while(!done);
		Log.d("Random Color", "Done Generating");*/
		
		for(int i = 0; i < colors.length; i+=4) {
			Random random = new Random();
			float a = random.nextFloat(), b=random.nextFloat(), c=random.nextFloat();
			colors[i] = a;
			colors[i+1] =b;
			colors[i+2] = c;
			colors[i+3] = 1.0f;
		}	

		colorBuffer.put(colors);
		colorBuffer.position(0);

	}
	
	public void makeColors(int color){
		Log.e("Color", Color.red(color) + " "+Color.green(color) + " "+Color.blue(color) + " "+Color.alpha(color));
		float r = Color.red(color)/255, g = Color.green(color)/255, b = Color.blue(color)/255, a = Color.alpha(color)/255;
		ByteBuffer byteBuffer11 = ByteBuffer.allocateDirect(4*size*4);
		byteBuffer11.order(ByteOrder.nativeOrder());
		colorBuffer = byteBuffer11.asFloatBuffer();
		colorBuffer.clear();
		colorBuffer.position(0);
		
		float[] colors = new float[4*numPoints];
	
		for(int i = 0; i < colors.length; i+=4) {
			float fi = (float)i;
			colors[i] = ((fi*r)%colors.length)/(colors.length);
			colors[i+1] = ((fi*g)%colors.length)/(colors.length);
			colors[i+2] = ((fi*b)%colors.length)/(colors.length);
			colors[i+3] = ((fi*a)%colors.length)/(colors.length);
		}	

		colorBuffer.put(colors);
		colorBuffer.position(0);

	}


	public void draw(GL10 gl, String type){
		if(ready) {
			if(type.equalsIgnoreCase("texture")){
				gl.glEnable(GL10.GL_TEXTURE_2D);
				gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
				gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

				for(int i = 0; i < nEdges+1; i++) {
					gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, indexBuffer[i].capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer[i]);
				}

				gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

				for(int i = 0; i < 2; i++) {
					gl.glDrawElements(GL10.GL_TRIANGLE_FAN, indexBuffer[i+nEdges].capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer[i+nEdges]);	
				}

				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			}

			else if(type.equalsIgnoreCase("color")||type.equalsIgnoreCase("randomcolor")){
				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
				gl.glShadeModel(GL10.GL_FLAT);
				gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

				for(int i = 0; i < nEdges+1; i++) {
					gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, indexBuffer[i].capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer[i]);
				}

				for(int i = 0; i < 2; i++) {
					gl.glDrawElements(GL10.GL_TRIANGLE_FAN, indexBuffer[i+nEdges].capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer[i+nEdges]);

				}

				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
			}
			
			else{
				gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
				gl.glColor4f(1, 1, 1, 1);
				gl.glShadeModel(GL10.GL_FLAT);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

				for(int i = 0; i < nEdges+1; i++) {
					gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, indexBuffer[i].capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer[i]);
				}

				for(int i = 0; i < 2; i++) {
					gl.glDrawElements(GL10.GL_TRIANGLE_FAN, indexBuffer[i+nEdges].capacity(), GL10.GL_UNSIGNED_SHORT, indexBuffer[i+nEdges]);

				}

				gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			}
		}
	}
}
